<html lang="en-US">

<head>
    
<title>Go 新语法挺丑？最新的泛型类型约束介绍 - 花落雨忧</title>

<meta property="og:title" content="Go 新语法挺丑？最新的泛型类型约束介绍 - 花落雨忧">



    



    
    <meta property="description" content="大家好，我是煎鱼。
近期我们在分享《3 件与 Go 开发者有关的大小事》时，里面有一部分有提到 Go 泛型的约束类型语法又又又变了。
在评论区里看到不少的读者朋友大呼泛型的新类型约束语法挺丑，不如原本的好&amp;hellip;
如下：
为此，今天煎鱼就带大家来看看，为什么会发生泛型的新语法会这种改变？
[&amp;hellip;] 原本 @Ian Lance Taylor 设计的的泛型类型关键字如下： &amp;hellip;">
    <meta property="og:description" content="大家好，我是煎鱼。
近期我们在分享《3 件与 Go 开发者有关的大小事》时，里面有一部分有提到 Go 泛型的约束类型语法又又又变了。
在评论区里看到不少的读者朋友大呼泛型的新类型约束语法挺丑，不如原本的好&amp;hellip;
如下：
为此，今天煎鱼就带大家来看看，为什么会发生泛型的新语法会这种改变？
[&amp;hellip;] 原本 @Ian Lance Taylor 设计的的泛型类型关键字如下： &amp;hellip;">
    






<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1">

<link rel="shortcut icon" href="https://www.lican.asia/logo/logo.png" type="image/x-icon" />



<link rel="stylesheet" href="/css/style.min.css" />

<link rel="stylesheet" href="/css/reset.min.css" />




<script src="https://www.lican.asia/js/highlight.min.js"></script>

<script>
hljs.configure({ ignoreUnescapedHTML: true })
hljs.highlightAll();
</script>


<script src="https://www.lican.asia/js/jquery.min.js"></script>




<link href="https://www.lican.asia/css/hugo-code.min.css" rel="stylesheet" />



    <style>
        .post-content img {
            max-width: 400px;
        }
    </style>
</head>

<body id="period" class="home blog">
    <a class="skip-content" href="#main">Press "Enter" to skip to content</a>
    <div id="overflow-container" class="overflow-container">
        <header class="site-header" id="site-header" role="banner">
    <div class="max-width">
        <div id="title-container" class="title-container">
            <div id="site-title" class="site-title"><a href="/">花落雨忧</a></div>
            <p class="tagline">思所及 力所行 方为真.</p>
        </div>
        
        <div id="menu-primary-container" class="menu-primary-container">
            <div class="icon-container">
            </div>
            <div id="menu-primary" class="menu-container menu-primary" role="navigation">
                <nav class="menu">
                    <ul id="menu-primary-items" class="menu-primary-items">
                        
                        
                        <li id="menu-item-0"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/posts" aria-current="page" tabindex="0">首页</a></li>
                        
                        <li id="menu-item-1"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/tech/" aria-current="page" tabindex="1">技术文档</a></li>
                        
                        <li id="menu-item-2"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/article/" aria-current="page" tabindex="2">文章</a></li>
                        
                        <li id="menu-item-3"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/project/" aria-current="page" tabindex="3">项目</a></li>
                        
                        <li id="menu-item-4"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/about/" aria-current="page" tabindex="4">关于</a></li>
                        
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</header>

        <div id="primary-container" class="primary-container">
            <div class="max-width">
                <section id="main" class="main" role="main">
                    <div id="loop-container" class="loop-container">
                        <div
                            class="post type-post status-publish format-standard hentry entry">
                            <article>
                                <div class="post-container">
                                    <div class="post-header">
                                        <h2 class="post-title">
                                            <a href="/posts/posts/go/118-constraints/">Go 新语法挺丑？最新的泛型类型约束介绍</a>
                                        </h2>
                                        
                                        <div class="post-byline">Published on
                                            <a class="date" href="javascript:;">2021/12/31</a>
                                            
                                            
                                            
                                            
                                            
                                        
                                    </div>
                                    <div class="post-content">
                                        <p>大家好，我是煎鱼。</p>
<p>近期我们在分享《<a href="https://mp.weixin.qq.com/s/22TeQOUjf_glPX3QLPX8yw">3 件与 Go 开发者有关的大小事</a>》时，里面有一部分有提到 Go 泛型的约束类型语法又又又变了。</p>
<p>在评论区里看到不少的读者朋友大呼泛型的新类型约束语法挺丑，不如原本的好&hellip;</p>
<p>如下：</p>
<p><img src="https://files.mdnice.com/user/3610/8e734a8f-612c-41c3-a0cd-8a5fe6eea483.png" alt=""></p>
<p>为此，今天煎鱼就带大家来看看，为什么会发生泛型的新语法会这种改变？</p>
<h2 id="问题背景">问题背景</h2>
<p>原本 @Ian Lance Taylor 设计的的泛型类型关键字如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">T</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">type</span> <span style="color:#66d9ef">int</span>, <span style="color:#66d9ef">int8</span>, <span style="color:#66d9ef">int16</span>, <span style="color:#66d9ef">int32</span>, <span style="color:#66d9ef">int64</span>, <span style="color:#66d9ef">uint</span>, <span style="color:#66d9ef">uint8</span>, <span style="color:#66d9ef">uint16</span>, <span style="color:#66d9ef">uint32</span>, <span style="color:#66d9ef">uint64</span>, <span style="color:#66d9ef">uintptr</span>, <span style="color:#66d9ef">float32</span>, <span style="color:#66d9ef">float64</span>, <span style="color:#66d9ef">complex64</span>, <span style="color:#66d9ef">complex128</span>, <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>看起来好像非常 “顺眼”。但在《<a href="https://github.com/golang/go/issues/41716" title="proposal: Go 2: sum types using interface type lists">proposal: Go 2: sum types using interface type lists</a>》中社区进行了热烈的讨论。</p>
<p>认为该类型约束的关键字，过于 “模棱两可”。像是 @Damien Neil 所提出的以下两个例子。</p>
<p>结构体的例子：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">p</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">mustIncludeDefaultCase</span> <span style="color:#66d9ef">struct</span>{}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">MySum</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">type</span> <span style="color:#66d9ef">int</span>, <span style="color:#66d9ef">float64</span>, <span style="color:#a6e22e">mustIncludeDefaultCase</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>不明确的点之一，如果类型列表包含一个未导出的类型，那又应该是如何处理呢？</p>
<p>接口的例子：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">T</span> <span style="color:#66d9ef">interface</span> { <span style="color:#66d9ef">type</span> <span style="color:#66d9ef">int16</span>, <span style="color:#66d9ef">int32</span> }
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">x</span> <span style="color:#a6e22e">T</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">switch</span> <span style="color:#a6e22e">x</span>.(<span style="color:#66d9ef">type</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">int16</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">int32</span>:
</span></span><span style="display:flex;"><span>  } 
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>你认为程序会跑进哪个 switch-case 的代码块里呢，是 int16，还是 int32？</p>
<p>不，都不会，变量 x 是 nil，如此迷惑。</p>
<p>在社区讨论中，发现设计与真实场景一结合，发现这个类型规则在普通的接口类型、在约束中使用也太微妙了。</p>
<p>用类型列表嵌入接口时的行为也很奇怪。认为可以做的更好，那就是 “更显式”。</p>
<h2 id="新提案">新提案</h2>
<p>为此，Go 泛型的设计者 @Ian Lance Taylor 提出了一个新的提案《<a href="https://github.com/golang/go/issues/45346" title="spec: generics: use type sets to remove type keyword in constraints">spec: generics: use type sets to remove type keyword in constraints</a>》。</p>
<p>其包含三个新的、更简单的想法来取代泛型提案中定义的类型列表。</p>
<h3 id="关键名词">关键名词</h3>
<p>新语法在泛型处增加一个新概念：接口元素（interface elements），用作约束条件的接口类型，或者被嵌入约束条件的接口类型，允许嵌入一些额外的构造。</p>
<p>被嵌入的可以是：</p>
<ul>
<li>任何类型，而不仅仅是一个接口类型。</li>
<li>一个新的句法结构，称为近似元素。</li>
<li>一个新的句法结构，称为联合元素。</li>
</ul>
<p>重点名词，我们继续展开讲解，分别是：</p>
<ul>
<li>嵌入约束。</li>
<li>近似元素。</li>
<li>联合元素。</li>
<li>接口类型。</li>
</ul>
<h3 id="联合元素">联合元素</h3>
<p>原先的语法中，类型约束会用逗号分隔的方式来展示。</p>
<p>如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#66d9ef">int</span>, <span style="color:#66d9ef">int8</span>, <span style="color:#66d9ef">int16</span>, <span style="color:#66d9ef">int32</span>, <span style="color:#66d9ef">int64</span>
</span></span></code></pre></div><p>在新语法中，结合定义为 union element（联合元素），写成一系列由竖线 ”|“ 分隔的类型或近似元素。</p>
<p>如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">PredeclaredSignedInteger</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> | <span style="color:#66d9ef">int8</span> | <span style="color:#66d9ef">int16</span> | <span style="color:#66d9ef">int32</span> | <span style="color:#66d9ef">int64</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>常常会和下面讲到的近似元素一起使用。</p>
<h3 id="近似元素">近似元素</h3>
<p>新语法，他的标识符是 “~”，完整用法是 <code>~T</code>。<code>~T</code> 是指底层类型为 T 的所有类型的集合。例如：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">AnyInt</span> <span style="color:#66d9ef">interface</span>{ ~<span style="color:#66d9ef">int</span> }
</span></span></code></pre></div><p>他的类型集是 <code>~int</code>，也就是所有类型为 int 的类型（如：int、int8、int16、int32、int64）都能够满足这个类型约束的条件。</p>
<p>再结合以上的分隔来使用，用法为：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">SignedInteger</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	~<span style="color:#66d9ef">int</span> | ~<span style="color:#66d9ef">int8</span> | ~<span style="color:#66d9ef">int16</span> | ~<span style="color:#66d9ef">int32</span> | ~<span style="color:#66d9ef">int64</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>相当于泛型提案中使用的以下类型：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">type</span> <span style="color:#66d9ef">int</span>, <span style="color:#66d9ef">int8</span>, <span style="color:#66d9ef">int16</span>, <span style="color:#66d9ef">int32</span>, <span style="color:#66d9ef">int64</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>新语法只需借助近似标识符 <code>~int</code> 来表达就可以了，更明确的表示了近似匹配，而不是存在隐式理解。</p>
<h3 id="嵌入约束">嵌入约束</h3>
<p>一个类型约束可以嵌入另一个约束，联合元素可以包括约束。</p>
<p>例如：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#75715e">// Signed is a constraint whose type set is any signed integer type.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Signed</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	~<span style="color:#66d9ef">int</span> | ~<span style="color:#66d9ef">int8</span> | ~<span style="color:#66d9ef">int16</span> | ~<span style="color:#66d9ef">int32</span> | ~<span style="color:#66d9ef">int64</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Unsigned is a constraint whose type set is any unsigned integer type.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Unsigned</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	~<span style="color:#66d9ef">uint</span> | ~<span style="color:#66d9ef">uint8</span> | ~<span style="color:#66d9ef">uint16</span> | ~<span style="color:#66d9ef">uint32</span> | ~<span style="color:#66d9ef">uint64</span> | ~<span style="color:#66d9ef">uintptr</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Float is a constraint whose type set is any floating point type.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Float</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	~<span style="color:#66d9ef">float32</span> | ~<span style="color:#66d9ef">float64</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Ordered is a constraint whose type set is any ordered type.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// That is, any type that supports the &lt; operator.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Ordered</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Signed</span> | <span style="color:#a6e22e">Unsigned</span> | <span style="color:#a6e22e">Float</span> | ~<span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>这个很好理解，就是正式支持嵌入约束了。</p>
<h3 id="接口类型联合约束元素">接口类型（联合约束元素）</h3>
<p>在联合元素中，使用接口类型的话。将会把该类型集添加到联合中。</p>
<p>例如：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Stringish</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">string</span> | <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Stringer</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Stringish 的类型集将是字符串类型和所有实现 <code>fmt.Stringer</code> 的类型，任何这些类型（包括 <code>fmt.Stringer</code> 本身）将被允许作为这个约束的类型参数。</p>
<p>也就是针对接口类型做了特殊的处理。</p>
<h2 id="总结">总结</h2>
<p>今天这篇文章，主要讲解了 Go 泛型的新语法，其实本质上还是为了解决引入 A 后，出现了 BCD 新问题，又继续引入新的语法和模式来解决。</p>
<p>整体就是三个观点：</p>
<ul>
<li>显式匹配：使用<strong>明确的 &ldquo;~&rdquo; 近似元素，澄清了何时在底层类型上进行匹配</strong>。</li>
<li>明确含义：<strong>使用 “|” 而不是 “,” 强调这是一个元素的联合</strong>。</li>
<li>嵌套优化：通过允许约束嵌入非界面元素，类型关键字可以被省略。</li>
</ul>
<p>这就是用这两个新语法符号的原因，被嫌丑的新语法标识符 “|” 和 “~” ，其实也是在 issues 的大范围讨论中，由社区贡献出来的。</p>
<p>算是有利有弊？<strong>你的看法如何，欢迎在评论区留言</strong>：）</p>


                                        
                                        
                                        
                                        <div class="rp4wp-related-posts">
                                            <h3>相关文章</h3>
                                            <ul>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/118-build/">泛型是双刃剑？Go1.18 编译会慢近 20%</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/news115/">分享 Go 最近的几件周边大小事</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/func-reload/">Go 为什么不支持函数重载和参数默认值？</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/118-leader-generics/">回归现实：Go Leader 对 1.18 泛型的期望</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/import-cyc/">为什么 Go 不支持循环引用？</a>
                                                    </div>
                                                </li>
                                                
                                            </ul>
                                        </div>
                                        
                                        
                                    </div>

                                    
                                    
                                    

                                    
                                    <div class="post-meta">
                                        
                                        
                                        <div class="post-tags">
                                            <ul>
                                            
                                            <li>
                                                <a href="/tags/go" title="View all posts tagged match">go</a>
                                            </li>
                                            
                                            </ul>
                                        </div>
                                        
                                        
                                        <nav class="further-reading">
                                            
                                            <div class="previous">
                                                <span>&lt;&lt; Prev</span>
                                                <a href="https://www.lican.asia/posts/posts/go/118-build/"
                                                    rel="prev">泛型是双刃剑？Go1.18 编译会慢近 20%</a> </div>
                                            
                                            
                                            <div class="next">
                                                <span>Next >></span>
                                                <a href="https://www.lican.asia/posts/posts/go/rust-php/">Rust 内讧，PHP 主力淡出？Go：好好放假</a> 
                                            </div>
                                            
                                        </nav>
                                    </div>
                                    
                                    

                                    
                                    
                                    

                                </div>
                            </article>
                        </div>
                    </div>
                </section>
                <aside class="sidebar sidebar-primary" id="sidebar-primary" role="complementary">
    <h1 class="screen-reader-text">Sidebar</h1>
    

    
    
    <section id="text-2" class="widget widget_text">
        <div class="textwidget">
            
            <div id="profile">
                <div id="profile_picture"><img src="https://www.lican.asia/logo/logo.png"></div>
                <div id="profile_intro">
                    <p><span class="name">Lican</span></p>
                    <p class="intro">全栈开发者，爱好造轮子。</p>
                </div>
            </div>
            
            <p>
                <script type="text/javascript">
                    (function ($) {
                        $(document).ready(function () {
                            var menuPrimaryContainer = $('#menu-primary-container');
                            var profile = $('#text-2');
                            $('#toggle-navigation').click(function () {
                                if (menuPrimaryContainer.hasClass('open')) {
                                    profile.removeClass('open');
                                } else {
                                    profile.addClass('open');
                                }
                            });
                        });
                    })(jQuery);
                </script>
            </p>
        </div>
    </section>
    
    
    
    
    
    <section id="text-5" class="widget widget_text">
        <h2 class="widget-title">开源项目</h2>
        <div class="textwidget">
            <div id="projects" style="line-height: 22px;">
                
                <a href="https://github.com/idoubi/gonews"
                    target="_blank">gonews</a>: &nbsp;Daily news for golang<br>
                
                <a href="https://github.com/idoubi/sql2struct"
                    target="_blank">sql2struct</a>: &nbsp;Generate go struct according to SQL<br>
                
                <a href="https://github.com/idoubi/goz"
                    target="_blank">goz</a>: &nbsp;Request library used in golang<br>
                
        </div>
    </section>
    
    

    
    
    
    
    <section id="qrcode" class="widget widget_media_image">
        <h2 class="widget-title">微信公众号</h2>
        <img width="258" height="258"
            src="https://www.lican.asia/wechat/lican.png"
            class="image wp-image-5514  attachment-full size-full" alt=""
            style="max-width: 100%; height: auto;"
            sizes="(max-width: 258px) 100vw, 258px">
    </section>
    
    

    
    
    

    
    
    

    
    
    
    
</aside>
            </div>
        </div>

        <footer id="site-footer" class="site-footer" role="contentinfo">
    <div class="max-width">
    </div>
    <div class="footer">
        <div id="footercontent">
            © lican.asia All rights reserved<br/>
            Built with Hugo Theme <a href="https://github.com/idoubi/hugo-theme-period" target="_blank">Period</a>
        </div>
    </div>
</footer>

<script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?e8351b6d4626d5881d439ea1f6184baa";
      var s = document.getElementsByTagName("script")[0]; 
      s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    
    </div>
    
</body>

</html>